//////////////////////////////////////////////////////////////////////////////////////
//
//  FileName    :   KG_FileMapping.h
//  Version     :   1.0
//  Creator     :   Freeway Chen, Zhu Chengmin
//  Date        :   2009-7-7
//  Comment     :   
//
//////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifdef _MSC_VER
#define XY_MAP_COPY     FILE_MAP_COPY       // Can write in memory, not write back to disk
#define XY_MAP_WRITE    FILE_MAP_WRITE      // Write to disk
#define XY_MAP_READ     FILE_MAP_READ       // Read only
#endif

#ifdef __linux
#define XY_MAP_COPY     0x0001              // (PROT_READ | PROT_WRITE) + MAP_PRIVATE
#define XY_MAP_WRITE    0x0002              // (PROT_READ | PROT_WRITE) + MAP_SHARED
#define XY_MAP_READ     0x0004              // PROT_READ + MAP_SHARED
#endif


struct IXY_FileMappingBuffer : public IUnknown
{
    virtual size_t GetSize() = 0;
    virtual void *GetData() = 0;
};

struct IXY_FileMapping : public IUnknown
{
    virtual int MapView(size_t uOffset, size_t uSize, IXY_FileMappingBuffer **ppRetBuffer) = 0;
    virtual int GetFileSize(size_t *puRetFileSize) = 0;
};

class XY_FileMappingBuffer : public IXY_FileMappingBuffer
{
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { return -1; }
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    virtual size_t GetSize() { return m_uSize; }
    virtual void *GetData() { return m_pvData; }
public:
    XY_FileMappingBuffer(
        IXY_FileMapping *piParentFileMapping,         
        size_t uSize,
        void *pvData,
        size_t uAlignedSize,
        void *pvAlignedData
    );
    virtual ~XY_FileMappingBuffer();
private:
    volatile long    m_lRefCount;
    
    IXY_FileMapping *m_piFileMapping;
    void            *m_pvData;
    size_t           m_uSize;
    void            *m_pvAlignedData;
    size_t           m_uAlignedSize;
};

class XY_FileMapping : public IXY_FileMapping
{
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { return -1; }
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    virtual int MapView(size_t uOffset, size_t uSize, IXY_FileMappingBuffer **ppRetBuffer);
    virtual int GetFileSize(size_t *puRetFileSize);
public:
    XY_FileMapping(int nFile, HANDLE hFileMapping, unsigned uMapFlag);
    virtual ~XY_FileMapping();
private:
    volatile long   m_lRefCount;

    int             m_nFile;
    HANDLE        m_hFileMapping;
    unsigned        m_uMapFlag;
};

PLATFORM_API int XY_CreateFileMapping(const char cszFileName[], unsigned uMapFlag, IXY_FileMapping **ppRetFileMapping);

